import { _decorator, Component, instantiate, Node, NodePool, tween, Tween, UIOpacity, Widget } from 'cc';
import { Ab_BasePopUp_bA } from '../../../A-FRAME/component/ui.pop-up';
import { Ab_EGamePopup_bA, Ab_GamePopIns_bA, Ab_GamePopParams_bA, Ab_GamePopReturn_bA, Ab_GetGamePopComponent_bA, Ab_GetGamePopPrefab_bA } from '../pop-up/popup.game.config';
const { ccclass, property } = _decorator;

@ccclass('Ab_GamePopup_bA')
export class Ab_GamePopup_bA extends Component {
	private static Ab__ins_bA: Ab_GamePopup_bA;
	/** 全局唯一安全实例 */
	public static get Ab_ins_bA(){
		return Ab_GamePopup_bA.Ab__ins_bA;
	}

	private Ab_hide_map_bA: Map<Ab_EGamePopup_bA, NodePool>;
	private Ab_shade_list_bA: UIOpacity[];

	private Ab_opacity_bA: number = 200;
	private Ab_duration_bA: number = 0.25;
	private get Ab_dur_half_bA(){
		return this.Ab_duration_bA * 0.5;
	}

	protected onLoad(){
		Ab_GamePopup_bA.Ab__ins_bA = this;

		this.Ab_init_bA();
	}

	private Ab_init_bA(){
		this.node.active = false;
		this.Ab_hide_map_bA = new Map();
		this.Ab_shade_list_bA = this.node.children.filter(n=>n.name==='___shade').map(n=>n.getComponent(UIOpacity));
		this.Ab_shade_list_bA.forEach(shade=>{
			shade.node.active = true;
			shade.opacity = 0;
		});

		this.Ab_preload_bA();
	}

	private async Ab_getInsNode_bA<P extends Ab_EGamePopup_bA>(p: P): Promise<Node>{
		let node: Node;
		if(this.Ab_hide_map_bA.has(p) && this.Ab_hide_map_bA.get(p).size()>0) node = this.Ab_hide_map_bA.get(p).get();
		else node = instantiate(await Ab_GetGamePopPrefab_bA(p));

		return node;
	}

	private async Ab_preload_bA(){
		[
			Ab_EGamePopup_bA.Ab_SETTING_bA,
			Ab_EGamePopup_bA.Ab_VICTORY_bA,
		].forEach(p=>this.Ab_getInsNode_bA(p).then(node=>{
			if(!this.Ab_hide_map_bA.has(p)) this.Ab_hide_map_bA.set(p, new NodePool());
			this.Ab_hide_map_bA.get(p).put(node);
		}));
	}

	private async Ab_activePop_bA<P extends Ab_EGamePopup_bA>(p: P): Promise<Ab_GamePopIns_bA<P>>{
		let node = await this.Ab_getInsNode_bA(p);

		node.active = false;
		node.setParent(this.node);

		// @ts-ignore
		return node.getComponent(await Ab_GetGamePopComponent_bA(p));
	}

	private Ab___shade_ref__bA: number = 0;
	private Ab_addShade_bA(){
		let duration = this.Ab_duration_bA * 1;
		this.Ab___shade_ref__bA++;

		let slist = this.Ab_shade_list_bA.map(shade=>{
			Tween.stopAllByTarget(shade);
			let wgt = shade.getComponent(Widget);
			if(wgt) wgt.updateAlignment();
			return {shade, z: shade.node.getSiblingIndex()};
		}).sort((a, b)=>b.z-a.z);

		let tw_list: Tween<UIOpacity>[] = [];

		if(this.Ab___shade_ref__bA===1){
			slist.forEach(el=>el.shade.opacity = 0);
			tw_list.push(tween(slist[1].shade).to(duration, {opacity: this.Ab_opacity_bA}));
		}else{
			let fixed_z = this.Ab___shade_ref__bA-1;
			let fixed_i = slist.findIndex(el=>el.z===fixed_z);
			let fixed_shade: UIOpacity;
			if(fixed_i>=0) fixed_shade = slist.splice(fixed_i, 1)[0].shade;
			else{
				fixed_shade = slist.pop().shade;
				fixed_shade.node.setSiblingIndex(fixed_z);
			}

			slist[0].shade.node.setSiblingIndex(this.Ab___shade_ref__bA);
			slist[0].shade.opacity = 0;
			fixed_shade.opacity = this.Ab_opacity_bA;

			tw_list.push(tween(fixed_shade).to(duration, {opacity: 0}, {progress(start, end, current, ratio) {
				let total = start-end;
				return 255 * total * (1-ratio) / (255 - total * ratio);
			}}));
			tw_list.push(tween(slist[0].shade).to(duration, {opacity: this.Ab_opacity_bA}))
		}

		tw_list.forEach(tw=>tw.start());
	}

	private Ab_cutShade_bA(){
		let duration = this.Ab_duration_bA * 1;
		this.Ab___shade_ref__bA--;

		let slist = this.Ab_shade_list_bA.map(shade=>{
			Tween.stopAllByTarget(shade);
			return {shade, z: shade.node.getSiblingIndex()};
		}).sort((a, b)=>b.z-a.z);

		let tw_list: Tween<UIOpacity>[] = [];

		if(this.Ab___shade_ref__bA===0) tw_list.push(tween(slist[1].shade).to(duration, {opacity: 0}));
		else{
			let fixed_z = this.Ab___shade_ref__bA-1;
			let fixed_i = slist.findIndex(el=>el.z===fixed_z);
			let fixed_shade: UIOpacity;
			if(fixed_i>=0) fixed_shade = slist.splice(fixed_i, 1)[0].shade;
			else{
				fixed_shade = slist.shift().shade;
				fixed_shade.node.setSiblingIndex(fixed_z);
			}
			fixed_shade.opacity = 0;
			slist[0].shade.opacity = this.Ab_opacity_bA;
			slist[0].shade.node.setSiblingIndex(this.Ab___shade_ref__bA+1);

			tw_list.push(tween(fixed_shade).to(duration, {opacity: this.Ab_opacity_bA}, {progress(start, end, curr, ratio){
				let total = end-start;
				return 255 * total * ratio / (255 - total * (1-ratio));
			}}));
			tw_list.push(
				tween(slist[0].shade).to(duration, {opacity: 0})
				.call(()=>slist[0].shade.node.setSiblingIndex(this.Ab___shade_ref__bA>1?this.Ab___shade_ref__bA-2:0))
			);
		}

		tw_list.forEach(tw=>tw.start());
	}

	private Ab_on_going_bA: Ab_EGamePopup_bA[] = [];

	private async Ab_show_bA<P extends Ab_EGamePopup_bA>(p: P, ...args: Ab_GamePopParams_bA<P>): Promise<Ab_GamePopReturn_bA<P>>{
		if(this.Ab_on_going_bA.includes(p)) return void 0;
		else this.Ab_on_going_bA.push(p);

		if(!this.node.active) this.node.active = true;
		this.Ab_addShade_bA();

		let pop = await this.Ab_activePop_bA(p);
		abi.Ab_log_bA.Ab_tag_bA(`SHOW-POP: chartreuse; ${pop.Ab_comp_name_bA}: lightyellow;`);

		let result: any;
		if(pop){
			result = await pop.Ab_show_bA(Ab_GamePopup_bA, ...args);
			Ab_GamePopup_bA.Ab_ins_bA.Ab_close_bA(p, pop);
		}else result = undefined;

		return result;
	}

	private Ab_close_bA<P extends Ab_EGamePopup_bA, C extends Ab_BasePopUp_bA<typeof Ab_GamePopup_bA, unknown>>(p: P, comp: C){
		if(this.Ab_on_going_bA.includes(p)) abi.Ab_array_bA.Ab_remove_bA(this.Ab_on_going_bA, p);

		if(this.node.children.includes(comp.node)){
			abi.Ab_log_bA.Ab_tag_bA(`CLOSE-POP: crimson; ${comp.Ab_comp_name_bA}: lightyellow;`);
			this.Ab_cutShade_bA();

			comp.node.active = false;
			if(!this.Ab_hide_map_bA.has(p)) this.Ab_hide_map_bA.set(p, new NodePool());
			this.Ab_hide_map_bA.get(p).put(comp.node);
		}

		if(this.Ab___shade_ref__bA<=0 && !(this.Ab_on_going_bA.length>0)) this.node.active = false;
	}

	public static async Ab_Setting_bA(...args: Ab_GamePopParams_bA<Ab_EGamePopup_bA.Ab_SETTING_bA>){
		return Ab_GamePopup_bA.Ab_ins_bA.Ab_show_bA(Ab_EGamePopup_bA.Ab_SETTING_bA, ...args);
	}

	public static async Ab_Victory_bA(...args: Ab_GamePopParams_bA<Ab_EGamePopup_bA.Ab_VICTORY_bA>){
		return Ab_GamePopup_bA.Ab_ins_bA.Ab_show_bA(Ab_EGamePopup_bA.Ab_VICTORY_bA, ...args);
	}
}

